/*
    * Author:   Sander
    * Date:     15-apr-2011
    * Name:     OBJModel
    * Version:  1.0
    *
    * This code is property of Sander blahblahblah copyright blahblah.
*/


package javaraytracer.Objects;

import javaraytracer.IntersectionInfo;
import javaraytracer.Materials.Material;
import javaraytracer.Ray;
import javaraytracer.Vec3;
import javaraytracer.parsers.OBJParser;
import javaraytracer.parsers.ParseData;

//PENDING:add function/property description
public class OBJModel extends Traceable
{
	private Vec3 position;
	private Vec3 rotation;
	private Traceable boundingSphere;
	private Mesh[] polygons;
	private double scale;

	public OBJModel(Vec3 pos, String model)
	{
		loadModel(model, pos, Vec3.EMPTY, 1.0, null);
	}
	public OBJModel(Vec3 pos, String model, Vec3 rot)
	{
		loadModel(model, pos, rot, 1.0, null);
	}
	public OBJModel(Vec3 pos, String model, Vec3 rot, double scale)
	{
		loadModel(model, pos, rot, scale, null);
	}
	public OBJModel(Vec3 pos, String model, Vec3 rot, double scale, Material mat)
	{
		loadModel(model, pos, rot, scale, mat);
	}

	private void loadModel(String file, Vec3 pos, Vec3 rot, double scale, Material mat)
	{
		position = pos;
		rotation = rot;
		material = mat;
		this.scale = scale;
		
		// load model
		ParseData data = OBJParser.parse(file, position, rotation, material, scale);
		polygons = data.polygons;
		boundingSphere = data.bounding;
		for(int i = 0; i < polygons.length; i++)
		{
			polygons[i].setParent((Traceable)this);
		}
		material = polygons[0].material;
		data = null;
	}


	@Override
	public IntersectionInfo intersect(Ray r)
	{
		//return boundingSphere.intersect(r);
		
		IntersectionInfo nearestHit = null;

		if(boundingSphere.intersect(r).hit)
		{
			for(int i = 0; i < polygons.length; i++)
			{
				IntersectionInfo ii = polygons[i].intersect(r);
				if(ii.hit && (nearestHit == null || ii.distance < nearestHit.distance))
				{
					nearestHit = ii;
				}
			}
			if(nearestHit != null)
			{
				return nearestHit;
			}
		}
		
		return new IntersectionInfo(false);
	}


	@Override
	public boolean hit(Ray r)
	{
		//return boundingSphere.hit(r);
		
		if(boundingSphere.hit(r))
		{
			for(int i = 0; i < polygons.length; i++)
			{
				if(polygons[i].hit(r))
				{
					return true;
				}
			}
		}
		return false;
	}


	@Override
	public Material getMaterial()
	{
		return material;
	}


	@Override
	public Material getMaterial(IntersectionInfo info)
	{
		return material;
	}

}
